package model;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import util.Constantes;
import util.Util;
import bean.DadosEntradaRNA;
import bean.PacoteE;
import bean.PacoteF;
import bean.PacoteT;


//Valor maximo 16bits = 65535
// Caso o contador volte ao inicio o tempo passa a ser recalculado
// Ex: tempo = 00025 -> tempo = 1*65535 + 00025 = 65560
public class RegistroPerfilMagnetico {

	private List<PacoteF> fluxos = null;
	private PacoteT pacoteT = null;
	private PacoteE pacoteE = null;
	private DadosEntradaRNA dadosEntradaRNA = null;
	
//	public RegistroPerfilMagnetico() {
//		
//	}
	
	public RegistroPerfilMagnetico(List<PacoteF> fluxos, PacoteT pacoteT, PacoteE pacoteE) {
		this.fluxos = fluxos;
		this.pacoteT = pacoteT;
		this.pacoteE = pacoteE;
		this.dadosEntradaRNA = null;
	}
	
	public DadosEntradaRNA geraDadosEntradaRNA(){
		return geraDadosEntradaRNA(this.fluxos);
	}
	
	public DadosEntradaRNA geraDadosEntradaRNA(List<PacoteF> fluxos){
		DadosEntradaRNA dadosEntradaRNA = null;
		
		int limite_excitacao_laco = 7;
		
		if(fluxos != null && fluxos.size() > 1){
			dadosEntradaRNA = new DadosEntradaRNA();
			
			int[] tempo = new int[fluxos.size()];
            int[] laco1 = new int[fluxos.size()];
            int[] laco2 = new int[fluxos.size()];
            
            int ma = 0; //valor_max_laco_1
            int mb = 0; //valor_max_laco_2
            int aa = 0; //area_laco_1
            int ab = 0; //area_laco_2
            int ta = 0; //tempo_laco_1
            int tb = 0; //tempo_laco_2
            int td = 0; //tempo_deslocamento
            int na = 1; //num_picos_laco_A
            int nb = 1; //num_picos_laco_B
            
            boolean inicio_tempo_laco_1 = false;
            boolean inicio_tempo_laco_2 = false;
            boolean executaNa = false;
            boolean executaNb = false;
            
            int tempoInicialA = 0;
            int tempoInicialB = 0;
            
            //TODO
            for (int i = 0; i < fluxos.size(); i++) {
				laco1[i] = fluxos.get(i).getCampoLaco1();
				laco2[i] = fluxos.get(i).getCampoLaco2();
				
				if(laco1[i] > ma){
					ma = laco1[i];
				}				
				if(laco2[i] > mb){
					mb = laco2[i];
				}
            }
            //
            
            for (int i = 0; i < fluxos.size(); i++) {
				tempo[i] = fluxos.get(i).getTempo();
				laco1[i] = fluxos.get(i).getCampoLaco1();
				laco2[i] = fluxos.get(i).getCampoLaco2();
				
				//TODO
				if(ma > 45){
					limite_excitacao_laco = (int) (ma * 0.2);
					
					if(limite_excitacao_laco < 7){
						limite_excitacao_laco = 7;
					}
				}
				//
				
				if(laco1[i] < limite_excitacao_laco){
					laco1[i] = 0;
				} 
				if(laco2[i] < limite_excitacao_laco){
					laco2[i] = 0;
				}
								
				if(i > 1){
					if((laco1[i - 1] > laco1[i]) && (laco1[i - 1] > laco1[i - 2])){
						if(executaNa == true){
							++na;
						} else{
							executaNa = true;
						}						
//						++na;
					} 
					
					if((laco2[i - 1] > laco2[i]) && (laco2[i - 1] > laco2[i - 2])){
						if(executaNb == true){
							++nb;
						} else{
							executaNb = true;
						}						
//						++nb;
					}
				}
				
//				if(laco1[i] > ma){
//					ma = laco1[i];
//				}				
//				if(laco2[i] > mb){
//					mb = laco2[i];
//				}
								
				//TEMPO INICIAL
				if((laco1[i] > 0) && (inicio_tempo_laco_1 == false)){
					inicio_tempo_laco_1 = true;
					tempoInicialA = tempo[i];
				}
				
				//TEMPO DO LACO A
//				if((laco1[i] == 0) && (i > 1)){
				if( (laco1[i] == 0) && (i > ((fluxos.size()-1) / 3)) ){
					if((ta == 0) && (ma > 0)){
//						ta = tempo[i];
						ta = tempo[i] - tempoInicialA;
					}
				}

				//TEMPO DE DESLOCAMENTO
				if((laco2[i] > 0) && (inicio_tempo_laco_2 == false)){
					inicio_tempo_laco_2 = true;
//					td = tempo[i];
					td = tempo[i] - tempoInicialA;
					tempoInicialB = tempo[i];
				}
				
				//TEMPO DO LACO B
				if((laco2[i] == 0) && (inicio_tempo_laco_2 == true) && (i > (85/100) * fluxos.size()) ){
//				if(((laco2[i] == 0) && (inicio_tempo_laco_2 == true)) || (i == (fluxos.size() - 1))){ //FUNCIONAL!!
//				if((inicio_tempo_laco_2 == true) && (i == (fluxos.size() - 1))){
//					if((tb == 0) && (mb > 0)){
//					if(mb > 0){
//						tb = tempo[i] - td;
						tb = tempo[i] - tempoInicialB;
//					}
				}
			}
            
            if(td == 0){
            	td = ta;
            }
            
            if(tb == 0){
            	tb = ta;
            }            	
            
            //integral de a ate b
            int a = 0;            
            int b = getTamanhoX(laco1);
            int n = b;
            
            aa = simpson(laco1, a, b, n);
            
            b = getTamanhoX(laco2);    
            n = b;
            
            ab = simpson(laco2, a, b, n);
            
            int saidaIdeal = Util.getPorte(getPacoteE().getPorteVeiculo());
               
//            System.out.println("tempo inicial: " + tempoInicialA);
//            System.out.println("ta: " + ta);
//            System.out.println("tb: " + tb);
//            System.out.println("td: " + td);
            
            dadosEntradaRNA.setMa(ma);
            dadosEntradaRNA.setMb(mb);
            dadosEntradaRNA.setAa(aa);
            dadosEntradaRNA.setAb(ab);
            dadosEntradaRNA.setTa(ta);
            dadosEntradaRNA.setTb(tb);
            dadosEntradaRNA.setTd(td);
            dadosEntradaRNA.setNa(na);
//            dadosEntradaRNA.setNb(nb); //FIXME verificar se eh ou nao necessario este campo
            dadosEntradaRNA.setSaidaIdeal(saidaIdeal);

//            setDadosEntradaRNA(dadosEntradaRNA);
		}
		
		return dadosEntradaRNA;
	}
	
	private int getTamanhoX(int[] laco){
		int x = laco.length - 1;
		
		if(x % 2 == 0){ //se for par
        	x = laco.length - 1;
        } else{
        	x = laco.length - 2;
        }
		
		return x;
	}
	
	private int simpson(int[] laco, int a, int b, int n) {
		if(((n & 1) != 0) || (n == 0)){
			System.err.println("n deve ser um valor inteiro");
			return 0;
		}
		
		int soma = 0;
		int h = (b - a) / n;
		int x = a;
		
		for (int i = 0; i < n/2; i++) {
			soma += laco[x] + 2*laco[x+h];
			x += 2*h;
		}
		
		soma = 2*soma - laco[a] + laco[b];
		
		return (h*soma / 3);
	}
	
	public List<PacoteF> getFluxos() {
		return fluxos;
	}
	
	public PacoteT getPacoteT() {
		return pacoteT;
	}

	public PacoteE getPacoteE() {
		return pacoteE;
	}
	
	public DadosEntradaRNA getDadosEntradaRNA() {
		return dadosEntradaRNA;
	}
}